package com.greensam.pixelengine.pojo.base;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.util.CollectionUtils;

import java.io.Serial;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author Macro_Ray
 * @since 2025/6/13 15:03
 */
@Data
@Schema(title = "通用分页响应数据对象")
public class PaginationResponse<T> implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    @Schema(title = "总记录数")
    private long totalCount;

    @Schema(title = "每页记录数")
    private int pageSize;

    @Schema(title = "总页数")
    private int totalPage;

    @Schema(title = "当前页数")
    private int currentPage;

    @Schema(title = "列表数据")
    private List<T> list;

    /**
     * 分页
     *
     * @param list        列表数据
     * @param totalCount  总记录数
     * @param pageSize    每页记录数
     * @param currentPage 当前页数
     */
    public PaginationResponse(List<T> list, long totalCount, int pageSize, int currentPage) {
        this.list = list;
        this.totalCount = totalCount;
        this.pageSize = pageSize;
        this.currentPage = currentPage;
        this.totalPage = (int) Math.ceil((double) totalCount / pageSize);
    }

    public boolean isEmpty() {
        return CollectionUtils.isEmpty(list);
    }

    public boolean hasNextPage() {
        return totalPage > currentPage;
    }

    public static <T> PaginationResponse<T> page(List<T> records, long totalCount, int pageSize, int currentPage) {
        return new PaginationResponse<>(records, totalCount, pageSize, currentPage);
    }

    public static <T> PaginationResponse<T> empty(int pageSize, int currentPage) {
        return new PaginationResponse<>(Collections.emptyList(), 0, pageSize, currentPage);
    }

    public <R> PaginationResponse<R> map(Function<T, R> function) {
        if (CollectionUtils.isEmpty(this.list)) {
            return PaginationResponse.empty(this.pageSize, this.currentPage);
        }
        List<R> result = this.getList().stream().map(function).collect(Collectors.toList());
        return new PaginationResponse<>(result, this.totalCount, this.pageSize, this.currentPage);
    }

    public PaginationResponse<T> filter(Predicate<T> predicate) {
        if (CollectionUtils.isEmpty(this.list)) {
            return PaginationResponse.empty(this.pageSize, this.currentPage);
        }
        List<T> result = this.getList().stream().filter(predicate).collect(Collectors.toList());
        return new PaginationResponse<>(result, this.totalCount, this.pageSize, this.currentPage);
    }
}
